package com.xinghanlaser.applet.base.auth.security.config;

import com.xinghanlaser.applet.base.auth.security.component.PermsFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import javax.annotation.Resource;
import java.util.Collections;

/**
 * @author dym
 * @date 2019-09-18 11:23
 */
@Configuration
@EnableResourceServer
public class ResourcesServerConfig extends ResourceServerConfigurerAdapter {
    @Resource
    private AuthenticationSuccessHandler authenticationSuccessHandler;

    @Resource
    private AuthenticationFailureHandler authenticationFailureHandler;

    @Resource
    private AuthenticationEntryPoint authenticationEntryPoint;

    @Resource
    private AccessDeniedHandler accessDeniedHandler;

    @Resource
    private PermsFilter permsFilter;


    @Override
    public void configure(ResourceServerSecurityConfigurer resources){
        resources.authenticationEntryPoint(authenticationEntryPoint);
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
            .cors().and() // 允许CORS

            .csrf().disable()
            .addFilterAfter(permsFilter, UsernamePasswordAuthenticationFilter.class)
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()

            .formLogin()
            .loginProcessingUrl("/admin/login") // 设置登录处理的RUL
            .successHandler(authenticationSuccessHandler) // 设置登录成功的处理器
            .failureHandler(authenticationFailureHandler).and() // 设置登录失败的处理器
            .exceptionHandling()
            .authenticationEntryPoint(authenticationEntryPoint) // 处理用户认证未通过的处理器
            .accessDeniedHandler(accessDeniedHandler).and() // 处理用户认证通过，却没有对应资源权限的处理器

            .requestMatchers()
            .antMatchers(
                    "/admin/**",
                    "/topic/**",
//                    "/knowledge/**",
                    "/flow/**"
            ).and() // TODO 需要认证的接口,只有拦截后才可以获取到Token里面的用户名信息

            .authorizeRequests()
            .antMatchers(HttpMethod.OPTIONS).permitAll()
            .antMatchers(
                    "/admin/login",
                    "/swagger-ui.html",
                    "/admin/phone-code/**",
                    "/test/**"
            ).permitAll() // TODO 不需要认证的接口

            .anyRequest().authenticated(); // 其他请求需要认证
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Collections.singletonList("*"));
        configuration.setAllowedMethods(Collections.singletonList("*"));
        configuration.setAllowedHeaders(Collections.singletonList("*"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}
